package com.luyu.caffeinedemo.config;


import cn.hutool.core.collection.CollUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Expiry;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;

/**
 * 自定义
 * @author luYuHan
 * @date 2023/8/6 16:22
 */
@Component
@Slf4j
public class MyExpireAfter implements Expiry {
    private static  Cache<String, ArrayList<Cache<String,String>>> cacheAll;
    @Autowired
    public static void setCacheAll(Cache<String, ArrayList<Cache<String, String>>> cacheAll) {
        MyExpireAfter.cacheAll = cacheAll;
    }

    @Override
    public long expireAfterCreate(@NonNull Object key, @NonNull Object value, long currentTime) {
        System.out.println("创建-------------创建");
        ArrayList<Cache<String, String>> list = (ArrayList<Cache<String, String>>) value;
        list.forEach(item -> {
            System.out.println("创建list:key=" + item.asMap().keySet() + ",value=" + item.asMap().values());
        });
        System.out.println("创建-------------创建");
        long expireTime = getExpireTime(key, value);
        System.out.println("创建-------------创建");
        return expireTime;
    }

    @Override
    public long expireAfterUpdate(@NonNull Object key, @NonNull Object value, long currentTime, @NonNegative long currentDuration) {
        System.out.println("更新-------------更新");
        ArrayList<Cache<String, String>> updateList = (ArrayList<Cache<String, String>>) value;
        updateList.forEach(item -> {
            System.out.println("读取list:key=" + item.asMap().keySet() + ",value=" + item.asMap().values() + ",state:" + item.stats());
        });
        System.out.println("更新-------------更新");
        long expireTime = getExpireTime(key, value);
        getExpireTime(key,value);
        System.out.println("更新-------------更新");
        return expireTime;
    }

    @Override
    public long expireAfterRead(@NonNull Object key, @NonNull Object value, long currentTime, @NonNegative long currentDuration) {
        System.out.println("读取-------------读取");
        ArrayList<Cache<String, String>> readLIST = (ArrayList<Cache<String, String>>) value;
        readLIST.forEach(item -> {
            System.out.println("读取list:key=" + item.asMap().keySet() + ",value=" + item.asMap().values() + ",state:" + item.stats());
        });
        System.out.println("读取-------------读取");
        long expireTime = getExpireTime(key, value);
        System.out.println("读取-------------读取");
        return expireTime;
    }


    public static synchronized long getExpireTime(Object key,Object value) {
        if (value instanceof ArrayList) {
            ArrayList<Cache<String, String>> list = (ArrayList<Cache<String, String>>) value;
            if (CollUtil.isEmpty(list)){
                return 0;
            }
            // 清除list中无用cache
            list.removeIf(item -> {
                if (CollUtil.isEmpty(item.asMap().keySet())){
                    item.invalidateAll();
                    return true;
                }
                return false;
            });
            list.forEach(item -> log.info("读取剩下:key=" + item.asMap().keySet() + ",value=" + item.asMap().values() + ",state:" + item.stats()));
            // 如果对应账号下的list清空进行赋值为null，等待回收
            if (CollUtil.isEmpty(list)) {
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally {
                    log.info("当前所剩下的key:"+cacheAll.asMap().keySet());
                    if (CollUtil.isNotEmpty(cacheAll.asMap().keySet()) && cacheAll.asMap().keySet().contains(key)){
                        log.info("删除用户-------------------");
                        log.info("全部失效进行回收:key=" +key);
                        cacheAll.asMap().remove(key);
                        log.info("剩下的数据"+cacheAll.asMap().keySet());
                        log.info("删除用户-------------------");
                    }
                    return 0;
                }
            }
        }
        return Long.MAX_VALUE;
    }
}
